﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.IO;

namespace EclipseLib.Shared.Scripting
{
    public class GameScript
    {
        // Data Members
        List<string> Assemblies = new List<string>();
        string code = "";
        string ClassName;
        string FuncName;

        // Method Properties
        public List<string> References
        {
            get { return Assemblies; }
        }
        public string Code
        {
            get { return code; }
            set 
            { 
                code = value;

                string Pattern = @"public class (?<after>\w+)";
                MatchCollection Matches = Regex.Matches(Code, Pattern);
                ClassName = Matches[0].Groups["after"].Value;

                string FuncPattern = @"public object (?<after>\w+)";
                MatchCollection FuncMatches = Regex.Matches(Code, FuncPattern);
                FuncName = FuncMatches[0].Groups["after"].Value;
            }
        }
        public string Class
        {
            get { return ClassName; }
        }
        public string Function
        {
            get { return FuncName; }
            set { FuncName = value; }
        }

        // Constructors
        public GameScript() { }

        // Methods
        public void AddAssemblyReference(string DllFile)
        {
            if (Assemblies.Contains(DllFile))
                return;

            Assemblies.Add(DllFile);
        }
        public void RemoveAssembly(string DllFile)
        {
            if (Assemblies.Contains(DllFile))
                Assemblies.Remove(DllFile);
        }
        public void ClearAssemblies()
        {
            Assemblies.Clear();
        }
        public void ToXML(string File)
        {
            XmlTextWriter XWriter = new XmlTextWriter(File, null);
            XWriter.Formatting = Formatting.Indented;

            XWriter.WriteStartDocument();

            // Root Element
            XWriter.WriteStartElement("GameScript");
            {
                // Write out Info
                XWriter.WriteStartElement("Info");
                {
                    XWriter.WriteStartElement("Class");
                    XWriter.WriteValue(Class);
                    XWriter.WriteEndElement();

                    XWriter.WriteStartElement("Function");
                    XWriter.WriteValue(Function);
                    XWriter.WriteEndElement();
                }
                XWriter.WriteEndElement();

                // Write out Assemblies
                XWriter.WriteStartElement("Assemblies");
                {
                    for (int i = 0; i < Assemblies.Count; ++i)
                    {
                        XWriter.WriteStartElement("DLL");
                        XWriter.WriteValue(Assemblies[i]);
                        XWriter.WriteEndElement();
                    }
                }
                XWriter.WriteEndElement();

                // Write out the actual code
                XWriter.WriteStartElement("Code");
                {
                    XWriter.WriteValue(Code);
                }
                XWriter.WriteEndElement();
            }
            XWriter.WriteEndElement();

            XWriter.WriteEndDocument();
            XWriter.Close();
        }
        public void FromXML(string File)
        {
            XmlTextReader XReader = new XmlTextReader(File);
            ClearAssemblies();

            while (XReader.Read())
            {
                switch (XReader.NodeType)
                {
                    case XmlNodeType.Element:
                        {
                            switch (XReader.Name)
                            {
                                case "Class":
                                    ClassName = XReader.ReadString();
                                    break;

                                case "Function":
                                    FuncName = XReader.ReadString();
                                    break;

                                case "DLL":
                                    AddAssemblyReference(XReader.ReadString());
                                    break;

                                case "Code":
                                    code = XReader.ReadString();
                                    break;
                            }
                        }
                        break;
                }
            }

            XReader.Close();
        }
        public void ToBinary(string File)
        {
            FileStream Fstream = new FileStream(File, FileMode.Create);
            BinaryWriter Writer = new BinaryWriter(Fstream);
            {
                Writer.Write(Class);
                Writer.Write(Function);

                Writer.Write(Assemblies.Count);
                foreach (string DLL in Assemblies)
                    Writer.Write(DLL);

                Writer.Write(Code);
            }
            Writer.Close();
            Fstream.Close();
        }
        public void FromBinary(string File)
        {
            FileStream Fstream = new FileStream(File, FileMode.Open);
            BinaryReader Reader = new BinaryReader(Fstream);
            {
                ClearAssemblies();

                ClassName = Reader.ReadString();
                FuncName = Reader.ReadString();

                int NumAssemblies = Reader.ReadInt32();
                for (int i = 0; i < NumAssemblies; ++i)
                    AddAssemblyReference(Reader.ReadString());

                code = Reader.ReadString();
            }
            Reader.Close();
            Fstream.Close();
        }
    }
}
